namespace SimpleWebServices.Web.UI.Html
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using SimpleWebServices;
    using SimpleWebServices.Web.UI.Html.Elements;
    using Xunit;

    public sealed class LinkCollectionFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<LinkCollection>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .Implements<IEnumerable<Link>>()
                .Implements<IXmlSerializable>()
                .XmlRoot("links")
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            string xml =
                "<links>" +
                    "<link rel='canonical' href='http://example.com/resource.en.html' />" +
                    "<foo />" +
                "</links>";

            LinkCollection obj = xml.Deserialize<LinkCollection>();

            Assert.True(obj.Contains("canonical"));
        }

        [Fact]
        public void deserializeEmpty()
        {
            Assert.NotNull("<links/>".Deserialize<LinkCollection>());
        }

        [Fact]
        public void serialize()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate("1=count(/links/link[@rel='canonical'][@href='http://example.com/page.en.html'])"));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new LinkCollection());
        }

        [Fact]
        public void prop_Count()
        {
            Assert.True(new PropertyExpectations(typeof(LinkCollection).GetProperty("Count"))
                .TypeIs<int>()
                .DefaultValueIs(0)
                .Result);
        }

        [Fact]
        public void prop_Count_get()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.Equal<int>(1, obj.Count);
        }

        [Fact]
        public void indexer_stringRelationship_get()
        {
            Link expected = new Link
            {
                Relationship = "canonical",
                Hyperlink = new Uri("http://example.com/page.en.html")
            };

            LinkCollection obj = new LinkCollection
            {
                expected
            };

            Assert.Same(expected, obj["canonical"]);
        }

        [Fact]
        public void indexer_stringReverseLink_get()
        {
            Link expected = new Link
            {
                ReverseLink = "parent",
                Hyperlink = new Uri("http://example.com/page.en.html")
            };

            LinkCollection obj = new LinkCollection
            {
                expected
            };

            Assert.Same(expected, obj["parent"]);
        }

        [Fact]
        public void indexer_stringMissing_get()
        {
            Assert.Throws<KeyNotFoundException>(() => new LinkCollection()["missing"]);
        }

        [Fact]
        public void opEquality_LinkCollection_LinkCollection()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opEquality_LinkCollection_LinkCollectionDiffers()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "prev", Hyperlink = new Uri("http://example.com/prev.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "next", Hyperlink = new Uri("http://example.com/next.en.html") }
            };

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opEquality_LinkCollection_LinkCollectionSame()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = obj;

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opEquality_LinkCollectionNull_LinkCollection()
        {
            LinkCollection obj = null;

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opEquality_LinkCollection_LinkCollectionNull()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = null;

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opInequality_LinkCollection_LinkCollection()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.False(obj != comparand);
        }

        [Fact]
        public void opInequality_LinkCollection_LinkCollectionDiffers()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "prev", Hyperlink = new Uri("http://example.com/prev.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "next", Hyperlink = new Uri("http://example.com/next.en.html") }
            };

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opInequality_LinkCollection_LinkCollectionSame()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = obj;

            Assert.False(obj != comparand);
        }

        [Fact]
        public void opInequality_LinkCollectionNull_LinkCollection()
        {
            LinkCollection obj = null;

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opInequality_LinkCollection_LinkCollectionNull()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = null;

            Assert.True(obj != comparand);
        }

        [Fact]
        public void op_Add_LinkCollection()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = new LinkCollection();
            comparand.Add(obj);

            Assert.True(obj == comparand);
        }

        [Fact]
        public void op_Add_LinkCollectionNull()
        {
            Assert.Throws<ArgumentNullException>(() => new LinkCollection().Add(null as LinkCollection));
        }

        [Fact]
        public void op_Add_Link()
        {
            Link link = new Link
            {
                Relationship = "canonical",
                Hyperlink = new Uri("http://example.com/page.en.html")
            };

            LinkCollection obj = new LinkCollection
            {
                link
            };

            LinkCollection comparand = new LinkCollection();
            comparand.Add(link);

            Assert.True(obj == comparand);
        }

        [Fact]
        public void op_Add_LinkNull()
        {
            Assert.Throws<ArgumentNullException>(() => new LinkCollection().Add(null as Link));
        }

        [Fact]
        public void op_Contains_stringRelationship()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link
                {
                    Relationship = "canonical",
                    Hyperlink = new Uri("http://example.com/page.en.html")
                }
            };

            Assert.True(obj.Contains("canonical"));
        }

        [Fact]
        public void op_Contains_stringReverseLink()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link
                {
                    ReverseLink = "parent",
                    Hyperlink = new Uri("http://example.com/page.en.html")
                }
            };

            Assert.True(obj.Contains("parent"));
        }

        [Fact]
        public void op_Contains_stringFalse()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link
                {
                    Relationship = "prev",
                    Hyperlink = new Uri("http://example.com/prev.en.html")
                }
            };

            Assert.False(obj.Contains("next"));
        }

        [Fact]
        public void op_Contains_stringNull()
        {
            Assert.Throws<ArgumentNullException>(() => new LinkCollection().Contains(null as string));
        }

        [Fact]
        public void op_Contains_stringEmpty()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => new LinkCollection().Contains(string.Empty));
        }

        [Fact]
        public void op_Contains_LinkTrue()
        {
            Link link = new Link
            {
                Relationship = "canonical",
                Hyperlink = new Uri("http://example.com/page.en.html")
            };

            LinkCollection obj = new LinkCollection
            {
                link
            };

            Assert.True(obj.Contains(link));
        }

        [Fact]
        public void op_Contains_LinkFalse()
        {
            Link link = new Link
            {
                Relationship = "next",
                Hyperlink = new Uri("http://example.com/next.en.html")
            };

            LinkCollection obj = new LinkCollection
            {
                new Link
                {
                    Relationship = "prev",
                    Hyperlink = new Uri("http://example.com/prev.en.html")
                }
            };

            Assert.False(obj.Contains(link));
        }

        [Fact]
        public void op_Contains_LinkNull()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link
                {
                    Relationship = "prev",
                    Hyperlink = new Uri("http://example.com/prev.en.html")
                }
            };

            Assert.False(obj.Contains(null as Link));
        }

        [Fact]
        public void op_Equals_object()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.True(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_Equals_objectDiffer()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "prev", Hyperlink = new Uri("http://example.com/prev.en.html") }
            };

            LinkCollection comparand = new LinkCollection
            {
                new Link { Relationship = "next", Hyperlink = new Uri("http://example.com/next.en.html") }
            };

            Assert.False(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_Equals_objectSame()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            Assert.True(obj.Equals(obj as object));
        }

        [Fact]
        public void op_Equals_objectNull()
        {
            Assert.False(new LinkCollection().Equals(null as object));
        }

        [Fact]
        public void op_Equals_objectString()
        {
            Assert.False(new LinkCollection().Equals(string.Empty as object));
        }

        [Fact]
        public void op_GetHashCode()
        {
            LinkCollection obj = new LinkCollection
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.com/page.en.html") }
            };

            int expected = obj.ToString().GetHashCode();
            int actual = obj.GetHashCode();

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void IEnumerable_op_GetEnumerator()
        {
            Assert.NotNull((new LinkCollection() as IEnumerable).GetEnumerator());
        }

        [Fact]
        public void IEnumerableOfT_op_GetEnumerator()
        {
            Assert.NotNull((new LinkCollection() as IEnumerable<Link>).GetEnumerator());
        }

        [Fact]
        public void IXmlSerializable_op_GetSchema()
        {
            Assert.Throws<NotSupportedException>(() => (new LinkCollection() as IXmlSerializable).GetSchema());
        }

        [Fact]
        public void IXmlSerializable_op_ReadXml_XmlReaderNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new LinkCollection() as IXmlSerializable).ReadXml(null as XmlReader));
        }

        [Fact]
        public void IXmlSerializable_op_WriteXml_XmlWriterNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new LinkCollection() as IXmlSerializable).WriteXml(null as XmlWriter));
        }
    }
}